/*
 * Created on 2005/5/18
 */
package servidor;

/**
 * @author jefify
 */

import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.ServerNotActiveException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import servidor.localizacao.ILocalizacao;
import servidor.localizacao.LocalizacaoWAI;
import servidor.localizacao.LocalizacaoSimuladaImpl;
import servidor.roteamento.Caminho;
import servidor.roteamento.Grafo;
import servidor.roteamento.Principal;
import servidor.roteamento.Vertice;

import comum.Localizacao;

public class ServidorImpl extends UnicastRemoteObject implements Servidor {

	private static Principal principal;
	
	private static boolean flagSimulacao = true;
	
	private ILocalizacao localizacao;

	public ServidorImpl() throws RemoteException {
		super();
		if (principal == null) {
			principal = new Principal();
			if (flagSimulacao) {
				System.out.println("WAI - WBLS4WAI - modo SIMULACAO");
			    localizacao = new LocalizacaoSimuladaImpl();
			} else {
			    System.out.println("WAI - WBLS4WAI Listener conectando... Aguarde...");
			    //localizacao = new LocalizacaoEkahauImpl();
				//aqui jaz o Ekahau
			    localizacao = new LocalizacaoWAI();			    
				System.out.println("WAI - WBLS4WAI Listener conectado com sucesso");
			}
		}
		System.out.println("Instanciou um servidor");
	}

	public Localizacao[] geraRota(Localizacao ini, Localizacao fim, int restricao) {

		System.out.println("servidor.ServidorImpl.geraRota: ini = ( " + ini.getX() + ", " + ini.getY() + ", " + ini.getAndar() + " ); fim = ( " + fim.getX() + ", " + fim.getY() + ", " + fim.getAndar() + " )");

		double distanciaMinima = Double.MAX_VALUE;
		Vertice verticeInicial = null;
		Vertice verticeFinal  = null;
		Collection grafos = principal.getGrafoHierarquico();
		for (Iterator iter = grafos.iterator(); iter.hasNext();) {
			Grafo grafo = (Grafo) iter.next();
			if (grafo.getNivelHierarquico() == 2) {
				Collection vertices = grafo.getVertices();
				for (Iterator iterator = vertices.iterator(); iterator.hasNext();) {
					Vertice vertice = (Vertice) iterator.next();
					if (vertice.getLocalizacao().getAndar() == ini.getAndar()) {
						double distancia = vertice.getLocalizacao().distancia(ini);
						if (distancia < distanciaMinima) {
							verticeInicial = vertice;
							distanciaMinima = distancia;
						}
					}
					if (vertice.getLocalizacao().getAndar() == fim.getAndar()) {
						double distancia = vertice.getLocalizacao().distancia(fim);
						if (distancia == 0) {
							verticeFinal = vertice;
						}
					}
				}
			}
		}
		
		if (verticeInicial == null || verticeFinal == null) {
			//TODO: ERRO!!!
			System.out.println("ERRO: null???  inicial: " + verticeInicial + ", final: " + verticeFinal);
		}
		
		Grafo grafo = null;
		Caminho caminhoDesejado = principal.buscarCaminhoHierarquico(verticeInicial, verticeFinal, restricao);
		System.out.println("CAMINHO: " + caminhoDesejado);
		System.out.println("CUSTO: " + caminhoDesejado.getCusto());

		ArrayList verticesCaminho = caminhoDesejado.getVertices();
		// devolve tambem a localizacao original no primeiro ponto
		// para facilitar a avaliacao no lado do cliente.
		Localizacao[] array = new Localizacao[verticesCaminho.size()+1];
		array[0] = ini;
		for (int i = 0; i < verticesCaminho.size(); i++) {
			Vertice v = (Vertice) verticesCaminho.get(i);
			array[i+1] = v.getLocalizacao();
		}

		return array;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see servidor.Servidor#obtemLocalizacao()
	 */
//	static int x = 100;
//	static int y = 520;
//	static int andar = 0;
//	public Localizacao obtemLocalizacao(String enderecoIP) {
//		// TODO Auto-generated method stub
//		int delta = (int)((Math.random()-0.35) * 6);
//		x += delta;
//		delta = (int)((Math.random()-0.35) * 10);
//		y += delta;
//		System.out.println("[Servidor] localizacao do cliente: (" + x + ", " + y + ", 0)");
//		return new Localizacao(x, y, (andar)%2);
//	}
	public Localizacao obtemLocalizacao() {
		String enderecoIP = "127.0.0.1";
		try {
			enderecoIP = java.rmi.server.RemoteServer.getClientHost();
		} catch (ServerNotActiveException e) {
			e.printStackTrace();
		}
		Localizacao local = localizacao.obterLocalizacao(enderecoIP);
		System.out.println("[Servidor] cliente ("+enderecoIP+"): " + local);
		return local;
	}
	
	public Localizacao pegaLocalizacaoPeloNome(String strLocal) {
    	for (Iterator iter = principal.getGrafoHierarquico().iterator(); iter.hasNext();) {
    		Grafo grafo = (Grafo) iter.next();
            Vertice vertice = grafo.getVertice(strLocal);
            if (vertice != null) {
            	return vertice.getLocalizacao();
            }
        }
		return null;
	}

	
	public static void main(String args[]) {
	    
		//MODO SIMULA��O FOR�ADO
	    //if (args.length > 0 && args[0].equalsIgnoreCase("simulacao")) {
	        System.out.println("Inicializando modulo WAI - Guiamenos4WAI!");
	    //}
	    
		// Create and install a security manager
		if (System.getSecurityManager() == null) {
			System.setSecurityManager(new RMISecurityManager());
		}
		try {
			ServidorImpl obj = new ServidorImpl();
			// Bind this object instance to the name "HelloServer"
			Naming.rebind("Servidor", obj);
			System.out.println("Servidor registrado!");
			
			 InetAddress   in  = InetAddress.getLocalHost();
			 InetAddress[] all = InetAddress.getAllByName(in.getHostName());
			 for (int i=0; i<all.length; i++) {
			     System.out.println("  address = " + all[i]);
			 }
			
		} catch (Exception e) {
			System.out.println("ServidorImpl err: " + e.getMessage());
			e.printStackTrace();
		}

		//        GrafoLoader loader = new GrafoLoader("roteamento/grafoH.xml");
		//        Collection grafoHierarquico = loader.load();
		//        grafo = null;
		//        for (Iterator iter = grafoHierarquico.iterator(); iter.hasNext();) {
		//            grafo = (Grafo) iter.next();
		//            if (grafo.getNome().equalsIgnoreCase("Room 1W3")) break;
		//        }

	}

}
